package org.gpp.proj1.demo.particle;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import com.jme.app.AbstractGame;
import com.jme.app.SimpleGame;
import com.jme.image.Texture;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.util.TextureManager;
import com.jmex.effects.ParticleManager;
import com.jmex.model.XMLparser.JmeBinaryReader;
import com.jmex.model.XMLparser.Converters.MaxToJme;

public class ParticleDemo extends SimpleGame {

	// as coisas do scene graph
	private Node bikeModel;
	private Node node;
	private Node particleNode;
	
	private ParticleManager manager;

	/**
	 * @see com.jme.app.BaseSimpleGame#simpleInitGame()
	 */
	@Override
	protected void simpleInitGame() {

		display.setTitle("teste particulas");
		this.node = new Node("myNode");

		// Carrega o modelo
		// ==============================================================

		// cada tipo de modelo tem um conversor diferente
		// esse � de Studio Max para jME
		MaxToJme converter = new MaxToJme();
		// onde ta o arquivo com o modelo
		File modelFile = new File("./test/model/bike.3ds");
		ByteArrayOutputStream BO = new ByteArrayOutputStream();

		try {
			// le do arquivo e poe no stream
			converter.convert(new FileInputStream(modelFile), BO);
		} catch (IOException e) {
			System.out.println("IO problem writting the file!!!");
			System.out.println(e.getMessage());
			System.exit(1);
		}
		bikeModel = null;
		try {
			// le do stream e cria um node
			bikeModel = (Node) new JmeBinaryReader().loadBinaryFormat(
					new ByteArrayInputStream(BO.toByteArray()));

		} catch (IOException e) {
			System.out.println("darn exceptions:" + e.getMessage());
		}
		
		// coloca no n�
		this.node.attachChild(this.bikeModel);

		// carrega as particulas feitas no editor
		// ===============================================================
	
		this.manager = new ParticleManager(100);
		manager.setGravityForce(new Vector3f(0.0f, 0.0f, 0.0f));
		manager.setEmissionDirection(new Vector3f(0.0f, 0.0f, 1.0f));
		manager.setEmissionMaximumAngle(0.0f);
		manager.setEmissionMinimumAngle(0.0f);
		manager.setSpeed(0.6f);
		manager.setParticlesMinimumLifeTime(300.0f);
		manager.setStartSize(13.9f);
		manager.setEndSize(3.6f);
		manager.setStartColor(new ColorRGBA(1.0f, 0.4f, 0.0f, 1.0f));
		manager.setEndColor(new ColorRGBA(0.6f, 0.2f, 0.0f, 0.0f));
		manager.setRandomMod(0.90000004f);
		manager.setControlFlow(false);
		manager.setReleaseRate(100);
		manager.setReleaseVariance(0.0f);
		manager.setInitialVelocity(1.4699999f);
		manager.setParticleSpinSpeed(-0.5f);

		manager.warmUp(1000);
		manager.getParticles().addController(manager);

		this.particleNode = new Node("Particle Nodes");
				
		AlphaState as = display.getRenderer().createAlphaState();
	    as.setBlendEnabled(true);
	    as.setSrcFunction(AlphaState.SB_SRC_ALPHA);
	    as.setDstFunction(AlphaState.DB_ONE);
	    as.setTestEnabled(true);
	    as.setTestFunction(AlphaState.TF_GREATER);
	    as.setEnabled(true);

	    TextureState ts = display.getRenderer().createTextureState();
	    ts.setTexture(TextureManager.loadTexture("./res/textures/flaresmall.jpg", Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR));
	    ts.setEnabled(true);
	    
		ZBufferState zbuf = display.getRenderer().createZBufferState();
		zbuf.setWritable(false);
		zbuf.setEnabled(true);
		zbuf.setFunction(ZBufferState.CF_LEQUAL);
		
		
		this.particleNode.setRenderState(as);
		this.particleNode.setRenderState(ts);
		this.particleNode.setRenderState(zbuf);
		
		this.particleNode.attachChild(manager.getParticles());
		
		this.particleNode.lock();
		
		// coloca no n�
		this.node.attachChild(this.particleNode);

		// ============================================================

		// associando a tecla espa�o � a��o fire
		KeyBindingManager.getKeyBindingManager().add("fire", KeyInput.KEY_SPACE);

		// ============================================================

		// faz as tranformadas na c�mera
		cam.setLocation(new Vector3f(50.0f, 50.0f, -50.0f)); // transla��o
		cam.lookAt(new Vector3f(0,0,0), new Vector3f(0,1,0)); // rota��o
		cam.update();
		
		// faz as tranformadas na motinha
		bikeModel.setLocalScale(.1f); // escala
		
		// faz as tranformadas nas particulas tambem
		this.particleNode.setLocalScale(0.2f); // escala
		this.particleNode.setLocalTranslation(new Vector3f(6.5f, -5f, 10f)); // transla��o
				
		// enchendo o scene graph com o n�
		this.rootNode.attachChild(this.node);
		
		Quaternion y90 = new Quaternion();
		y90.fromAngleAxis(FastMath.PI/2, new Vector3f(0,1,0));
		this.rootNode.setLocalRotation(y90);		
	}

	/**
	 * @see com.jme.app.BaseSimpleGame#simpleUpdate()
	 */
	@Override
	protected void simpleUpdate() {
		
		// aqui � pra fazer alguma coisa quando o cara aperta espa�o
		if (KeyBindingManager.getKeyBindingManager().isValidCommand("fire",true)){

			// liga o canh�o eternamente
			this.particleNode.unlock();
        }
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ParticleDemo app = new ParticleDemo();
		app.setDialogBehaviour(AbstractGame.FIRSTRUN_OR_NOCONFIGFILE_SHOW_PROPS_DIALOG);
		app.start();
	}
}
